
#pragma once

#include "IEventListener.h"
#include "IEventManager.h"

#include <vector>
#include <list>
#include <set>
#include <map>



typedef std::vector<IEventListener::Ptr> EventListenerList;
typedef std::vector<EventType>      EventTypeList;



class EventManager : public IEventManager
{
public:

	static const char * const kpWildcardEventType;

	explicit EventManager( char const * const name );

	virtual ~EventManager();

	virtual bool AddListener ( IEventListener::Ptr const & listener, 
		EventType const & type );

	virtual bool RemListener ( IEventListener::Ptr const & listener,
		EventType const & type );

	virtual bool Trigger ( Event const & ev ) const;

	virtual bool QueueEvent ( Event::Ptr const & ev );

	virtual bool AbortEvent ( EventType const & type,
		bool all = false );

	virtual bool Update();

	virtual bool ValidateType( EventType const & type ) const;


	EventListenerList GetListenerList( EventType const & type ) const;

	EventTypeList GetTypeList() const;

private:

	// one global instance
	typedef std::set< EventType >						EventTypeSet;

	// insert result into event type set
	typedef std::pair< EventTypeSet::iterator, bool >		EventTypeSetIRes;

	// one list per event type ( stored in the map )
	typedef std::list< IEventListener::Ptr >					EventListenerTable;

	// mapping of event ident to listener list
	typedef std::map< unsigned int, EventListenerTable >	EventListenerMap;

	// entry in the event listener map
	typedef std::pair< unsigned int, EventListenerTable >	EventListenerMapEnt;

	// insert result into listener map
	typedef std::pair< EventListenerMap::iterator, bool >	EventListenerMapIRes;

	// queue of pending- or processing-events
	typedef std::list< Event::Ptr >							EventQueue;

	enum eConstants
	{
		kNumQueues = 2
	};

	EventTypeSet mTypeSet;           // list of registered
	// event types

	EventListenerMap mRegistry;           // mapping of event types
	// to listeners

	EventQueue mQueues[kNumQueues]; // event processing queue,
	// double buffered to
	// prevent infinite cycles

	int mActiveQueue;        // valid denoting which
	// queue is actively
	// processing, en-queing
	// events goes to the
	// opposing queue

};
